<template>
  <j-modal
    :title="title"
    :width="1400"
    :visible="visible"
    :confirmLoading="confirmLoading"
    switchFullscreen
    @ok="handleOk"
    @cancel="handleCancel"
    cancelText="关闭"
    class="formulaModal-dialog"
  >
    <a-spin :spinning="confirmLoading">
      <a-divider orientation="left">基本信息</a-divider>
      <a-form :form="form">
        <a-row>
          <a-col :span="12">
            <a-form-item
              :labelCol="labelCol"
              :wrapperCol="wrapperCol"
              label="名称">
              <a-input placeholder="请输入名称" v-decorator.trim="[ 'name', validatorRules.name]"/>
            </a-form-item>
          </a-col>
          <a-col :span="12">
            <a-form-item
              :labelCol="labelCol"
              :wrapperCol="wrapperCol"
              label="备注">
              <a-input placeholder="请输入备注" v-decorator.trim="[ 'description', validatorRules.description]"/>
            </a-form-item>
          </a-col>
          <!-- <a-col :span="12">
            <a-form-item
              :labelCol="labelCol12"
              :wrapperCol="wrapperCol12"
              label="数据类型">
              <a-input placeholder="请选择数据类型" v-decorator.trim="[ 'dictCode', validatorRules.dictCode]"/>
            </a-form-item>
          </a-col>
          <a-col :span="12">
            <a-form-item
              :labelCol="labelCol12"
              :wrapperCol="wrapperCol12"
              label="长度">
              <a-input placeholder="请输入长度" v-decorator.trim="[ 'dictCode', validatorRules.dictCode]"/>
            </a-form-item>
          </a-col>
          <a-col :span="12">
            <a-form-item
              :labelCol="labelCol12"
              :wrapperCol="wrapperCol12"
              label="小数精度">
              <a-input placeholder="请输入小数精度" v-decorator.trim="[ 'dictCode', validatorRules.dictCode]"/>
            </a-form-item>
          </a-col>
          <a-col :span="12">
            <a-form-item
              :labelCol="labelCol"
              :wrapperCol="wrapperCol"
              label="统计单位">
              <a-input placeholder="请输入统计单位" v-decorator.trim="[ 'dictCode', validatorRules.dictCode]"/>
            </a-form-item>
          </a-col> -->
        </a-row>
      </a-form>
      <a-divider orientation="left">公式信息</a-divider>
      <div class="bottom-content">
        <div class="left">
          <div class="operator-list">
            <template v-for="(item, index) in operators">
              <div
                :class="[
                  'operator-item'
                ]"
                :key="'operator' + index"
                draggable="true"
                @dragstart="event => dragstart(event, item)"
                @dragend="event => dragend(event, item)"
              >
                <p>{{ item }}</p>
              </div>
            </template>
          </div>
        </div>
        <div class="center">
          <a-row>
            <a-col :span="6"  v-for="(formula, index) in formulas" :key="'formula' + index" style="margin-top:20px">
              <div class="drop-left"  @dragover="event => dragover(event, 'left', index)" @drop="event => drop(event, index)"></div>
              <div class="drop-right"  @dragover="event => dragover(event, 'right', index)" @drop="event => drop(event, index)"></div>
              <div class="card">
                <a-button @click="handleRemove(index)" v-if="formulas.length > 1" type="text" icon="close" style="position:absolute;right:10px;top:0" />
                <div class="left">
                  <a-button @click="handleAdd('left',index)" type="text" icon="caret-left" style="float:right" />
                </div>
                <div class="center">
                  <a-input placeholder="" v-model="formula.value" :class="checkValue(formula.value) ? 'error-class' : ''"/>
                </div>
                <div class="right">
                  <a-button @click="handleAdd('right',index)" type="text" icon="caret-right" />
                </div>
              </div>
            </a-col>
          </a-row>
        </div>
        <div class="right">
          <a-button @click="handleView" type="primary" >公式预览</a-button>
          <!-- <a-icon type="question-circle"/> -->
        </div>
      </div>
    </a-spin>
    <a-modal v-model="gongshiVisible" title="公式查看">
      <p style="font-size:30px">{{gongshi}}</p>
      <template slot="footer">
        <a-button  @click="closeGongshi">关闭</a-button>
      </template>
    </a-modal>
  </j-modal>
</template>

<script>
import { httpAction } from '@/api/manage'
import pick from 'lodash.pick'
export default {
  name: 'FormulaModal',
  data() {
    return {
      gongshi: null,
      gongshiVisible: false,
      dragIndex: 0,
      operatorSelected: null,
      operators: ['+', '-', '*', '/', '(', ')', '%', '^', '!', '|', 'if', 'ifnull'],
      formulas: [
        { value: '' }
      ],
      value: 1,
      title: '操作',
      visible: false,
      model: {},
      labelCol: {
        xs: { span: 24 },
        sm: { span: 5 }
      },
      wrapperCol: {
        xs: { span: 24 },
        sm: { span: 16 }
      },
      confirmLoading: false,
      form: this.$form.createForm(this),
      validatorRules: {
        name: { rules: [{ required: true, message: '请输入公式名称!' }] },
        description: {
          rules: [{ required: true, message: '请输入公式描述!' }]
        }
      }
    }
  },
  created() {
  },
  methods: {
    // 验证公式
    checkCalcExpressionValid(string) {
      // 剔除空白符
      string = string.replace(/\s/g, '')

      // 错误情况，空字符串
      if (string === '') {
        return false
      }

      // 错误情况，运算符连续
      if (/[\+\-\*\/]{2,}/.test(string)) {
        return false
      }

      // 空括号
      if (/\(\)/.test(string)) {
        return false
      }

      // 空中括号
      if (/\[\]/.test(string)) {
        return false
      }

      // 错误情况，括号不配对
      var stack = []
      for (var i = 0, item; i < string.length; i++) {
        item = string.charAt(i)
        if (item === '(') {
          stack.push('(')
        } else if (item === ')') {
          if (stack.length > 0) {
            stack.pop()
          } else {
            return false
          }
        }
      }
      if (stack.length !== 0) {
        return false
      }

      // 错误情况，中括号不配对
      var stack2 = []
      for (var i = 0, item; i < string.length; i++) {
        item = string.charAt(i)
        if (item === '[') {
          stack2.push('[')
        } else if (item === ']') {
          if (stack2.length > 0) {
            stack2.pop()
          } else {
            return false
          }
        }
      }
      if (stack2.length !== 0) {
        return false
      }

      // 错误情况，(后面是运算符
      if (/\([\+\-\*\/]/.test(string)) {
        return false
      }

      // 错误情况，)前面是运算符
      if (/[\+\-\*\/]\)/.test(string)) {
        return false
      }

      // 错误情况，[后面是运算符
      if (/\[[\+\-\*\/]/.test(string)) {
        return false
      }

      // 错误情况，]前面是运算符
      if (/[\+\-\*\/]\]/.test(string)) {
        return false
      }

      // 错误情况，运算符号不能在首末位
      if (/^[\+\-\*\/.]|[\+\-\*\/.]$/.test(string)) {
        return false
      }

      // 错误情况，中括号结尾到下一个开始之间没有运算符
      if (/\]\[/.test(string)) {
        return false
      }

      return true
    },
    // 分解公式
    analysisFormula(val) {
      var strsTemp = val.split('')
      var strs = []
      var bianliang = ''
      strsTemp.forEach((item, index) => {
        if (this.isValid(item)) {
          bianliang += item
          if (index == strsTemp.length - 1) {
            strs.push(bianliang)
          }
        } else {
          if (bianliang != '') {
            strs.push(bianliang)
          }
          strs.push(item)
          bianliang = ''
        }
      })
      return strs
    },
    closeGongshi() {
      this.gongshiVisible = false
    },
    // 查看公式
    handleView() {
      var indexTemp = this.formulas.findIndex(item => {
        return this.checkValue(item.value)
      })
      if (indexTemp == -1) {
        var gongshi = ''
        this.formulas.forEach(item => {
          gongshi += item.value
        })
        if (this.checkCalcExpressionValid(gongshi)) {
          this.gongshi = gongshi
          this.gongshiVisible = true
        } else {
          this.$message.warning('公式格式错误')
        }
      } else {
        this.$message.warning('公式格式错误')
      }
    },
    // ************************************拖拽**************************************************** /
    dragover(event, flag, index) {
      console.log(flag)
      if (flag == 'left') {
        this.dragIndex = index
      } else {
        this.dragIndex = index + 1
      }
    },
    dragstart(event, val) {
      if (val) {
        this.operatorSelected = val
      }
    },
    dragend() {
      if (this.operatorSelected) {
        this.formulas.splice(this.dragIndex, 0, { value: this.operatorSelected })
      }
    },
    // ************************************拖拽**************************************************** /
    handleRemove(index) {
      this.formulas.splice(index, 1)
    },
    handleAdd(flag, index) {
      if (flag == 'right') {
        this.formulas.splice(index + 1, 0, { value: '' })
      } else {
        this.formulas.splice(index, 0, { value: '' })
      }
    },
    checkNum(value) {
      return !isNaN(parseFloat(value)) && isFinite(value)
    },
    checkValue(val) {
      if (val == null || val == '') {
        return true
      }
      if (this.checkNum(val)) {
        return false
      } else if (this.operators.find(item => item == val)) {
        return false
      } else {
        if (this.isValid(val)) {
          return false
        } else {
          return true
        }
      }
    },
    isValid(str) {
      return /^\w+$/.test(str)
    },
    add() {
      this.edit({})
    },
    edit(record) {
      if (record.id) {
        this.visiblekey = true
        var gongshis = this.analysisFormula(record.body)
        this.formulas = []
        gongshis.forEach(item => {
          this.formulas.push({ value: item })
        })
      } else {
        this.visiblekey = false
        this.formulas = [{ value: '' }]
      }
      this.form.resetFields()
      this.model = Object.assign({}, record)
      this.visible = true
      this.$nextTick(() => {
        this.form.setFieldsValue(pick(this.model, 'name', 'description'))
      })
    },
    // 确定
    handleOk() {
      const that = this
      // 触发表单验证
      this.form.validateFields((err, values) => {
        if (!err) {
          that.confirmLoading = true

          var params = values

          var indexTemp = this.formulas.findIndex(item => {
            return this.checkValue(item.value)
          })
          if (indexTemp == -1) {
            var gongshi = ''
            this.formulas.forEach(item => {
              gongshi += item.value
            })
            if (this.checkCalcExpressionValid(gongshi)) {
              params.body = gongshi

              var url = '/index/compute/scSituationFormula/add'
              var method = 'POST'

              if (this.model.id) {
                params.id = this.model.id
                url = '/index/compute/scSituationFormula/edit'
                method = 'PUT'
              }

              httpAction(url, params, method).then(res => {
                if (res.success) {
                  this.$emit('ok')
                  this.close()
                }
                that.confirmLoading = false
              })
            } else {
              this.$message.warning('公式格式错误')
              that.confirmLoading = false
            }
          } else {
            this.$message.warning('公式格式错误')
            that.confirmLoading = false
          }
        }
      })
    },
    // 关闭
    handleCancel() {
      this.close()
    },
    close() {
      this.formulas = [{ value: '' }]
      this.form.resetFields()
      this.visible = false
    }
  }
}
</script>
<style lang="less">
.formulaModal-dialog {
  .bottom-content {
    width: 100%;
    display: flex;

    .left {
      width: 200px;
      .operator-list {
        height: calc(100% );
        overflow-x: hidden;
        overflow-y: auto;
        padding: 10px 0;

        .operator-item {
          cursor: pointer;
          text-align: center;
          line-height: 36px;

          &:hover,
          &.active {
            background-color: #eff4f9;
          }
        }
      }
    }
    .right {
      width: 200px;
    }
    .center {
      width: calc(100% - 400px);
    }
  }
  .drop-left {
    width: 50%;
    height: 100px;
    position: absolute;
    left: 0;
  }
  .drop-right {
    width: 50%;
    height: 100px;
    position: absolute;
    right: 0;
  }
  .card {
    margin-left: 10px;
    border: 1px solid #cdcdcd;
      border-radius: 4px;
    padding: 20px;
    width: calc(100% - 20px);
    height: 100px;
    display: flex;
    .ant-btn {
      margin-right: 0px;
    }
    .left {
      display: flex;
      justify-content: space-around;
      align-items: center;
      flex-direction: row;
      width: 20%;
      height: 60px;
    }
    .center {
      width: 60%;
      height: 60px;
      .error-class {
        border-color: red !important;
      }
      .ant-input {
        text-align: center;
        height: 100%;
        font-size: 30px;
      }
    }
    .right {
      display: flex;
      justify-content: space-around;
      align-items: center;
      flex-direction: row;
      width: 20%;
      height: 60px;
    }
  }
}
</style>
